package com.http;

import com.alibaba.fastjson.JSONObject;
import com.util.SQLHelp;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.ResourceBundle;


@Component
public class BaiduOAuthConfig {
    public static String AppID ;

    public static String AppKey;
    public static String ScrectKey;
    public static String SignKey;

    public static String OAuthCodeUrl;
    public static String OAuthAccessTokenUrl;

    public static String CallBackUrl;

    static {
//       try {
//           Properties properties = new Properties();
//           InputStream inputStream = BaiduOAuthConfig.class.getClassLoader().getResourceAsStream("baidu.properties");
//           properties.load(inputStream);
//           AppID = properties.getProperty("oauth.appid");
//           AppKey = properties.getProperty("oauth.app-key");
//           ScrectKey = properties.getProperty("oauth.screct-key");
//           SignKey = properties.getProperty("oauth.sign-key");
//           OAuthCodeUrl = properties.getProperty("oauth.url.code");
//           OAuthAccessTokenUrl = properties.getProperty("oauth.url.access-token");
//           CallBackUrl = properties.getProperty("oauth.url.callback");
//       } catch (IOException e) {
//           throw new RuntimeException(e);
//       }
        // 方法4.2，ResourceBundle
        // https://blog.csdn.net/qq_38570633/article/details/109264186
        ResourceBundle resourceBundle = ResourceBundle.getBundle("baidu");
        AppID = resourceBundle.getString("oauth.appid");
        AppKey = resourceBundle.getString("oauth.app-key");
        ScrectKey = resourceBundle.getString("oauth.screct-key");
        SignKey = resourceBundle.getString("oauth.sign-key");
        OAuthCodeUrl = resourceBundle.getString("oauth.url.code");
        OAuthAccessTokenUrl = resourceBundle.getString("oauth.url.access-token");
        CallBackUrl = resourceBundle.getString("oauth.url.callback");
    }

    public static String getOAuthCodeUrl(){
        // code授权链接
        String url = String.format("%s?" +
                "response_type=code&" +
                "client_id=%s&" +
                "redirect_uri=%s&" +
                "scope=basic,netdisk&" +
                "device_id=%s", OAuthCodeUrl, AppKey, CallBackUrl, AppID);
        return url;
    }

    public static String getUserTokenFromBaiDu(int userId, int index, String code){
        // 获取用户的token
        String url = BaiduOAuthConfig.getOAuthAccessTokenUrl(code);
        try {
            JSONObject result =  HttpRequest.PostRequest(url);
            if(result == null || result.containsKey("error")){
                return "token_error";
            }
            // 有数据，保存一下
            String accessToken = (String) result.get("access_token");
            // 获取信息
            JSONObject info = getUserInfo(accessToken);
            if(info == null || !info.get("errno").equals(0)){
                return "info_error";
            }
            Integer uk = Integer.parseUnsignedInt(info.get("uk").toString());
            if(!saveTokenInfo(userId, index, result, uk)){
                return "pan_repeat";
            }
            return (String) result.get("access_token");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static JSONObject getUserInfo(String accessToken) throws IOException {
        // 获取用户的信息
        String url = BaiduPanConfig.getPanUserInfoUrl(accessToken);
        try {
            JSONObject result = HttpRequest.PostRequest(url);
            return result;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static String getOAuthAccessTokenUrl(String code){
        // 通过code获取token
        String url = String.format("%s?" +
                "grant_type=authorization_code&" +
                "code=%s&" +
                "client_id=%s&" +
                "client_secret=%s&" +
                "redirect_uri=%s", OAuthAccessTokenUrl, code, AppKey, ScrectKey, CallBackUrl);
        return url;
    }

    public static boolean saveTokenInfo(int userId, int index, JSONObject tokenInfo, Integer uk){
        String sqlFormat = "select * from baiduoauthtable where uk = %s;";
        String sql = String.format(sqlFormat, uk);
        if(!SQLHelp.selectQuery(sql).isEmpty()){
            // 重复了
            return false;
        }
        sqlFormat = "insert into BaiduOAuthTable (pan_id, user_id, access_token, refresh_token, expires_in, update_seconds, uk)" +
                "values(%s, %s, '%s', '%s', %s, %s, %s)";
        int tokenId = userId * 10 + index;
        String accessToken = tokenInfo.get("access_token").toString();
        String refreshToken = tokenInfo.get("refresh_token").toString();
        String expiresIn = tokenInfo.get("expires_in").toString();
        Long update_seconds = System.currentTimeMillis() / 1000;
        sql = String.format(sqlFormat, tokenId, userId, accessToken, refreshToken, expiresIn, update_seconds, uk);
        return SQLHelp.update(sql) == 1;
    }

    public static String checkAndGetPanAccessToken(String accessToken) throws IOException{
        String sql = "select access_token, refresh_token, update_seconds, expires_in from BaiduOAuthTable where access_token='" + accessToken + "';";
        ArrayList<HashMap<String,String>> res = SQLHelp.selectQuery(sql);
        if(res.isEmpty()){
            return accessToken;
        }
        long update_seconds = Long.parseLong(res.get(0).get("update_seconds"));
        int expires_in = Integer.parseInt(res.get(0).get("expires_in"));
        long now_seconds = System.currentTimeMillis() / 1000;
        if(update_seconds + expires_in < now_seconds){
            // 过期了
            String refreshToken = res.get(0).get("refresh_token");
            return refreshAccessToken(accessToken, refreshToken);
        }
        return accessToken;
    }

    public static String checkAndGetPanAccessToken(int panId) throws IOException {
        String sql = "select access_token, refresh_token, update_seconds, expires_in from BaiduOAuthTable where pan_id=" + panId + ";";
        ArrayList<HashMap<String,String>> res = SQLHelp.selectQuery(sql);
        if(res.isEmpty()){
            return "";
        }
        long update_seconds = Long.parseLong(res.get(0).get("update_seconds"));
        int expires_in = Integer.parseInt(res.get(0).get("expires_in"));
        long now_seconds = System.currentTimeMillis() / 1000;
        if(update_seconds + expires_in < now_seconds){
            // 过期了
            String refreshToken = res.get(0).get("refresh_token");
            String accessToken = refreshAccessToken(panId, refreshToken);
            if(accessToken.equals("")){
                accessToken = res.get(0).get("access_token");
            }
            return accessToken;
        }
        return res.get(0).get("access_token");
    }

    public static String checkAndGetPanAccessToken(int userId, int index) throws IOException {
        // panId是用户userId和用户网盘index组合起来的值
        // 比如用户userId=10086，他的第一个网盘的panId就是100861，第二个是100862
        int panId = userId * 10 + index;
        return checkAndGetPanAccessToken(panId);
    }

    public static String refreshAccessToken(int panId, String refreshToken) throws IOException {
        // access过期了之后的刷新
        String url = String.format("%s?" +
                "grant_type=refresh_token&" +
                "refresh_token=%s&" +
                "client_id=%s&" +
                "client_secret=%s", OAuthAccessTokenUrl, refreshToken, AppKey, ScrectKey);
        JSONObject result = HttpRequest.GetRequest(url);
        if(result.get("errno")!=null && !result.get("errno").equals(0)){

            System.out.println(url);
            return "";
        }
        String access_token = (String) result.get("access_token");
        if(access_token==null || access_token.equals("")){
            System.out.println(url);
            System.out.println("刷新token失败：" + result.toJSONString());
            return "";
        }
        String expires_in = result.get("expires_in").toString();
        String refresh_token = (String) result.get("refresh_token");
        Long update_seconds = System.currentTimeMillis() / 1000;
        String sqlFormat = "update BaiduOAuthTable set access_token='%s', expires_in=%s, refresh_token='%s', update_seconds=%s where pan_id = %s";
        String sql = String.format(sqlFormat, access_token, expires_in, refresh_token, update_seconds, panId);
        if(SQLHelp.update(sql)!=1){
            return "";
        }
        System.out.println("更新token成功：" + result.toJSONString());
        return access_token;
    }

    public static String refreshAccessToken(String accessToken, String refreshToken) throws IOException {
        // access过期了之后的刷新
        String url = String.format("%s?" +
                "grant_type=refresh_token&" +
                "refresh_token=%s&" +
                "client_id=%s&" +
                "client_secret=%s", OAuthAccessTokenUrl, refreshToken, AppKey, ScrectKey);
        JSONObject result = HttpRequest.GetRequest(url);
        if(result.get("errno")!=null && !result.get("errno").equals(0)){

            System.out.println(url);
            System.out.println("刷新token失败：" + result.toJSONString());
            return accessToken;
        }
        String access_token = (String) result.get("access_token");
        if(access_token==null || access_token.equals("")){
            System.out.println(url);
            System.out.println("刷新token失败：" + result.toJSONString());
            return accessToken;
        }
        String expires_in = result.get("expires_in").toString();
        String refresh_token = (String) result.get("refresh_token");
        Long update_seconds = System.currentTimeMillis() / 1000;
        String sqlFormat = "update BaiduOAuthTable set access_token='%s', expires_in=%s, refresh_token='%s', update_seconds=%s where access_token = '%s'";
        String sql = String.format(sqlFormat, access_token, expires_in, refresh_token, update_seconds, accessToken);
        if(SQLHelp.update(sql)!=1){
            return accessToken;
        }
        System.out.println("更新token成功：" + result.toJSONString());
        return access_token;
    }




}
